package com.longge.common.util;

import java.util.Map;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;

import lombok.NonNull;

/**
 * HTTP Rest Util
 * 
 * @author yangzhilong
 *
 */
public class RestTemplateUtils {
	private static RestTemplate restTemplate;
	
	private RestTemplateUtils() {}

	/**
	 * @param client
	 */
	public static void setRestTemplate(RestTemplate client) {
		restTemplate = client;
	}

	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param clasz
	 * @return
	 */
	public static <T> T get(@NonNull String url, @NonNull Class<T> clasz) {
		return restTemplate.getForObject(url, clasz);
	}
	
	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param clasz
	 * @return
	 */
	public static <T> T get(@NonNull String url, @NonNull Map<String, String> headerMap, @NonNull Class<T> clasz) {
		MultiValueMap<String, String> headers = new HttpHeaders();
		HttpEntity<Object> requestEntity = new HttpEntity<>(null, headers);
		ResponseEntity<T> entity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, clasz);
		return entity.getBody();
	}
	
	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param headerMap
	 * @param bodyObj
	 * @param clasz
	 * @return
	 */
	public static <T> T postJson(@NonNull String url, @NonNull Class<T> clasz) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.add("Accept", MediaType.APPLICATION_JSON.toString());
		HttpEntity<String> formEntity = new HttpEntity<String>("{}", headers);
		return restTemplate.postForObject(url, formEntity, clasz);
	}
	
	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param headerMap
	 * @param bodyObj
	 * @param clasz
	 * @return
	 */
	public static <T> T postJson(@NonNull String url, @NonNull Object bodyObj, @NonNull Class<T> clasz) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.add("Accept", MediaType.APPLICATION_JSON.toString());
		HttpEntity<String> formEntity = new HttpEntity<String>(JSON.toJSONString(bodyObj), headers);
		return restTemplate.postForObject(url, formEntity, clasz);
	}

	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param headerMap
	 * @param bodyObj
	 * @param clasz
	 * @return
	 */
	public static <T> T postJson(@NonNull String url, Map<String, String> headerMap, Object bodyObj, @NonNull Class<T> clasz) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.add("Accept", MediaType.APPLICATION_JSON.toString());
		if (null != headerMap && !headerMap.isEmpty()) {
			headerMap.entrySet().forEach(item -> {
				headers.add(item.getKey(), item.getValue());
			});
		}
		String result = null;
		if (bodyObj == null) {
			result = "{}";
		} else {
			result = JSON.toJSONString(bodyObj);
		}
		HttpEntity<String> formEntity = new HttpEntity<String>(result, headers);
		return restTemplate.postForObject(url, formEntity, clasz);
	}
	
	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param clasz
	 * @return
	 */
	public static <T> T postForm(@NonNull String url, @NonNull Class<T> clasz) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(null, headers);
		return restTemplate.exchange(url, HttpMethod.POST, requestEntity, clasz).getBody();
	}

	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param attrMap
	 * @param clasz
	 * @return
	 */
	public static <T> T postForm(@NonNull String url, @NonNull Map<String, String> attrMap, @NonNull Class<T> clasz) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		attrMap.entrySet().forEach(item -> {
			params.add(item.getKey(), item.getValue());
		});
		HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
		return restTemplate.exchange(url, HttpMethod.POST, requestEntity, clasz).getBody();
	}


	/**
	 * 
	 * @param <T>
	 * @param url
	 * @param attrMap
	 * @param headerMap
	 * @param clasz
	 * @return
	 */
	public static <T> T postForm(@NonNull String url, Map<String, String> attrMap, @NonNull Map<String, String> headerMap,
			@NonNull Class<T> clasz) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		if (null != headerMap && !headerMap.isEmpty()) {
			headerMap.entrySet().forEach(item -> {
				headers.add(item.getKey(), item.getValue());
			});
		}

		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		attrMap.entrySet().forEach(item -> {
			params.add(item.getKey(), item.getValue());
		});
		HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
		return restTemplate.exchange(url, HttpMethod.POST, requestEntity, clasz).getBody();
	}
}